package org.hibernate.cfg;

import java.util.Properties;

import org.hibernate.cfg.reveng.ReverseEngineeringSettings;
import org.hibernate.cfg.reveng.dialect.H2MetaDataDialect;
import org.hibernate.cfg.reveng.dialect.HSQLMetaDataDialect;
import org.hibernate.cfg.reveng.dialect.MetaDataDialect;
import org.hibernate.cfg.reveng.dialect.MySQLMetaDataDialect;
import org.hibernate.cfg.reveng.dialect.OracleMetaDataDialect;
import org.hibernate.cfg.reveng.dialect.SQLServerMetaDataDialect;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.dialect.HSQLDialect;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.Oracle8iDialect;
import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.util.ReflectHelper;

/**
 * MetaDataDialectFactory
 * 
 * @author iPan
 * @version 2013-08-04
 */
public class MetaDataDialectFactory {

	/**
	 * 创建MetaDataDialect
	 * 先根据hibernate配置信息创建，再根据Dialect创建；
	 * 该方法比较灵活，创建方式，两者可以选其一，另一个参数可以直接设null；
	 * 默认只支持oracle、mysql、sqlserver、h2、hsql；其他数据库，采用Properties配置文件方式来指定，并自行实现MetaDataDialect接口；
	 * 
	 * @param dialect hibernate方言
	 * @param cfg hibernate配置
	 * @return MetaDataDialect
	 */
	public static MetaDataDialect createMetaDataDialect(Dialect dialect, Properties cfg) {
		MetaDataDialect mdd = null;
		if (cfg != null) {
			String property = cfg.getProperty(ReverseEngineeringSettings.META_DATA_DIALECT);
			mdd = fromClassName(property);
		}
		if (mdd == null) {
			mdd = fromDialect(dialect);
		}
		return mdd;
	}

	private static MetaDataDialect fromClassName(String property) {
		if (property != null) {
			try {
				return (MetaDataDialect) ReflectHelper.classForName(property, JDBCReaderFactory.class).newInstance();
			} catch (Exception e) {
				throw new JDBCBinderException("Could not load MetaDataDialect: " + property, e);
			}
		} else {
			return null;
		}
	}

	public static MetaDataDialect fromDialect(Dialect dialect) {
		if (dialect != null) {
			if (dialect instanceof Oracle8iDialect) {
				return new OracleMetaDataDialect();
			} else if (dialect instanceof MySQLDialect) {
				return new MySQLMetaDataDialect();
			} else if (dialect instanceof H2Dialect) {
				return new H2MetaDataDialect();
			} else if (dialect instanceof HSQLDialect) {
				return new HSQLMetaDataDialect();
			} else if (dialect instanceof SQLServerDialect) {
				return new SQLServerMetaDataDialect();
			}
		}
		return null;
	}

	public static MetaDataDialect fromDialectName(String dialect) {
		if (dialect.toLowerCase().contains("oracle")) {
			return new OracleMetaDataDialect();
		} else if (dialect.toLowerCase().contains("mysql")) {
			return new MySQLMetaDataDialect();
		} else if (dialect.toLowerCase().contains("h2")) {
			return new H2MetaDataDialect();
		} else if (dialect.toLowerCase().contains("hsql")) {
			return new HSQLMetaDataDialect();
		} else if (dialect.toLowerCase().contains("sqlserver")) {
			return new SQLServerMetaDataDialect();
		}
		return null;
	}

}
